home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Special 16 / AMIGAplus Sonderheft 16 (1998)(ICP)(DE)[!].iso / pd / anwendungen / ispell-3.1.18src / term.c < prev    next >
C/C++ Source or Header  |  1994-11-02  |  14KB  |  568 lines

  1. #ifndef lint
  2. static char Rcs_Id[] =
  3.     "$Id: term.c,v 1.48 1994/10/25 05:46:11 geoff Exp $";
  4. #endif
  5.  
  6. /*
  7.  * term.c - deal with termcap, and unix terminal mode settings
  8.  *
  9.  * Pace Willisson, 1983
  10.  *
  11.  * Copyright 1987, 1988, 1989, 1992, 1993, Geoff Kuenning, Granada Hills, CA
  12.  * All rights reserved.
  13.  *
  14.  * Redistribution and use in source and binary forms, with or without
  15.  * modification, are permitted provided that the following conditions
  16.  * are met:
  17.  *
  18.  * 1. Redistributions of source code must retain the above copyright
  19.  *    notice, this list of conditions and the following disclaimer.
  20.  * 2. Redistributions in binary form must reproduce the above copyright
  21.  *    notice, this list of conditions and the following disclaimer in the
  22.  *    documentation and/or other materials provided with the distribution.
  23.  * 3. All modifications to the source code must be clearly marked as
  24.  *    such.  Binary redistributions based on modified source code
  25.  *    must be clearly marked as modified versions in the documentation
  26.  *    and/or other materials provided with the distribution.
  27.  * 4. All advertising materials mentioning features or use of this software
  28.  *    must display the following acknowledgment:
  29.  *      This product includes software developed by Geoff Kuenning and
  30.  *      other unpaid contributors.
  31.  * 5. The name of Geoff Kuenning may not be used to endorse or promote
  32.  *    products derived from this software without specific prior
  33.  *    written permission.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS IS'' AND
  36.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  37.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  38.  * ARE DISCLAIMED.  IN NO EVENT SHALL GEOFF KUENNING OR CONTRIBUTORS BE LIABLE
  39.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  40.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  41.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  42.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  43.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  44.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  45.  * SUCH DAMAGE.
  46.  */
  47.  
  48. /*
  49.  * $Log: term.c,v $
  50.  * Revision 1.48  1994/10/25  05:46:11  geoff
  51.  * Fix a couple of places where ifdefs were omitted, though apparently
  52.  * harmlessly.
  53.  *
  54.  * Revision 1.47  1994/09/01  06:06:32  geoff
  55.  * Change erasechar/killchar to uerasechar/ukillchar to avoid
  56.  * shared-library problems on HP systems.
  57.  *
  58.  * Revision 1.46  1994/01/25  07:12:11  geoff
  59.  * Get rid of all old RCS log lines in preparation for the 3.1 release.
  60.  *
  61.  */
  62.  
  63. #include "config.h"
  64. #include "ispell.h"
  65. #include "proto.h"
  66. #include "msgs.h"
  67. #ifdef USG
  68. #include <termio.h>
  69. #else
  70. #include <sgtty.h>
  71. #endif
  72. #include <signal.h>
  73.  
  74. void        erase P ((void));
  75. void        move P ((int row, int col));
  76. void        inverse P ((void));
  77. void        normal P ((void));
  78. void        backup P ((void));
  79. static int    putch P ((int c));
  80. void        terminit P ((void));
  81. SIGNAL_TYPE    done P ((int signo));
  82. #ifdef SIGTSTP
  83. static SIGNAL_TYPE onstop P ((int signo));
  84. #endif /* SIGTSTP */
  85. void        stop P ((void));
  86. int        shellescape P ((char * buf));
  87. #ifdef USESH
  88. void        shescape P ((char * buf));
  89. #endif /* USESH */
  90.  
  91. void erase ()
  92.     {
  93.  
  94.     if (cl)
  95.     tputs (cl, li, putch);
  96.     else
  97.     {
  98.     if (ho)
  99.         tputs (ho, 100, putch);
  100.     else if (cm)
  101.         tputs (tgoto (cm, 0, 0), 100, putch);
  102.     tputs (cd, li, putch);
  103.     }
  104.     }
  105.  
  106. void move (row, col)
  107.     int        row;
  108.     int        col;
  109.     {
  110.     tputs (tgoto (cm, col, row), 100, putch);
  111.     }
  112.  
  113. void inverse ()
  114.     {
  115.     tputs (so, 10, putch);
  116.     }
  117.  
  118. void normal ()
  119.     {
  120.     tputs (se, 10, putch);
  121.     }
  122.  
  123. void backup ()
  124.     {
  125.     if (BC)
  126.     tputs (BC, 1, putch);
  127.     else
  128.     (void) putchar ('\b');
  129.     }
  130.  
  131. static int putch (c)
  132.     int            c;
  133.     {
  134.  
  135.     return putchar (c);
  136.     }
  137.  
  138. #ifdef USG
  139. static struct termio    sbuf;
  140. static struct termio    osbuf;
  141. #else
  142. static struct sgttyb    sbuf;
  143. static struct sgttyb    osbuf;
  144. #ifdef TIOCSLTC
  145. static struct ltchars    ltc;
  146. static struct ltchars    oltc;
  147. #endif
  148. #endif
  149. static int        termchanged = 0;
  150. static SIGNAL_TYPE    (*oldint) ();
  151. static SIGNAL_TYPE    (*oldterm) ();
  152. #ifdef SIGTSTP
  153. static SIGNAL_TYPE    (*oldttin) ();
  154. static SIGNAL_TYPE    (*oldttou) ();
  155. static SIGNAL_TYPE    (*oldtstp) ();
  156. #endif
  157.  
  158. void terminit ()
  159.     {
  160. #ifdef TIOCPGRP
  161.     int            tpgrp;
  162. #else
  163. #ifdef TIOCGPGRP
  164.     int            tpgrp;
  165. #endif
  166. #endif
  167. #ifdef TIOCGWINSZ
  168.     struct winsize    wsize;
  169. #endif /* TIOCGWINSZ */
  170.  
  171.     tgetent (termcap, getenv ("TERM"));
  172.     termptr = termstr;
  173.     BC = tgetstr ("bc", &termptr);
  174.     cd = tgetstr ("cd", &termptr);
  175.     cl = tgetstr ("cl", &termptr);
  176.     cm = tgetstr ("cm", &termptr);
  177.     ho = tgetstr ("ho", &termptr);
  178.     nd = tgetstr ("nd", &termptr);
  179.     so = tgetstr ("so", &termptr);    /* inverse video on */
  180.     se = tgetstr ("se", &termptr);    /* inverse video off */
  181.     if ((sg = tgetnum ("sg")) < 0)    /* space taken by so/se */
  182.     sg = 0;
  183.     ti = tgetstr ("ti", &termptr);    /* terminal initialization */
  184.     te = tgetstr ("te", &termptr);    /* terminal termination */
  185.     co = tgetnum ("co");
  186.     li = tgetnum ("li");
  187. #ifdef TIOCGWINSZ
  188.     if (ioctl (0, TIOCGWINSZ, (char *) &wsize) >= 0)
  189.     {
  190.     if (wsize.ws_col != 0)
  191.         co = wsize.ws_col;
  192.     if (wsize.ws_row != 0)
  193.         li = wsize.ws_row;
  194.     }
  195. #endif /* TIOCGWINSZ */
  196.     /*
  197.      * Let the variables "LINES" and "COLUMNS" override the termcap
  198.      * entry.  Technically, this is a terminfo-ism, but I think the
  199.      * vast majority of users will find it pretty handy.
  200.      */
  201.     if (getenv ("COLUMNS") != NULL)
  202.     co = atoi (getenv ("COLUMNS"));
  203.     if (getenv ("LINES") != NULL)
  204.     li = atoi (getenv ("LINES"));
  205. #if MAX_SCREEN_SIZE > 0
  206.     if (li > MAX_SCREEN_SIZE)
  207.     li = MAX_SCREEN_SIZE;
  208. #endif /* MAX_SCREEN_SIZE > 0 */
  209. #if MAXCONTEXT == MINCONTEXT
  210.     contextsize = MINCONTEXT;
  211. #else /* MAXCONTEXT == MINCONTEXT */
  212.     if (contextsize == 0)
  213. #ifdef CONTEXTROUNDUP
  214.     contextsize = (li * CONTEXTPCT + 99) / 100;
  215. #else /* CONTEXTROUNDUP */
  216.     contextsize = (li * CONTEXTPCT) / 100;
  217. #endif /* CONTEXTROUNDUP */
  218.     if (contextsize > MAXCONTEXT)
  219.     contextsize = MAXCONTEXT;
  220.     else if (contextsize < MINCONTEXT)
  221.     contextsize = MINCONTEXT;
  222. #endif /* MAX_CONTEXT == MIN_CONTEXT */
  223.     /*
  224.      * Insist on 2 lines for the screen header, 2 for blank lines
  225.      * separating areas of the screen, 2 for word choices, and 2 for
  226.      * the minimenu, plus however many are needed for context.  If
  227.      * possible, make the context smaller to fit on the screen.
  228.      */
  229.     if (li < contextsize + 8  &&  contextsize > MINCONTEXT)
  230.     {
  231.     contextsize = li - 8;
  232.     if (contextsize < MINCONTEXT)
  233.         contextsize = MINCONTEXT;
  234.     }
  235.     if (li < MINCONTEXT + 8)
  236.     (void) fprintf (stderr, TERM_C_SMALL_SCREEN, MINCONTEXT + 8);
  237.  
  238. #ifdef SIGTSTP
  239. #ifdef TIOCPGRP
  240. retry:
  241. #endif /* SIGTSTP */
  242. #endif /* TIOCPGRP */
  243.  
  244. #ifdef USG
  245.     if (!isatty (0))
  246.     {
  247.     (void) fprintf (stderr, TERM_C_NO_BATCH);
  248.     exit (1);
  249.     }
  250.     (void) ioctl (0, TCGETA, (char *) &osbuf);
  251.     termchanged = 1;
  252.  
  253.     sbuf = osbuf;
  254.     sbuf.c_lflag &= ~(ECHO | ECHOK | ECHONL | ICANON);
  255.     sbuf.c_oflag &= ~(OPOST);
  256.     sbuf.c_iflag &= ~(INLCR | IGNCR | ICRNL);
  257.     sbuf.c_cc[VMIN] = 1;
  258.     sbuf.c_cc[VTIME] = 1;
  259.     (void) ioctl (0, TCSETAW, (char *) &sbuf);
  260.  
  261.     uerasechar = osbuf.c_cc[VERASE];
  262.     ukillchar = osbuf.c_cc[VKILL];
  263.  
  264. #endif
  265.  
  266. #ifdef SIGTSTP
  267. #ifndef USG
  268.     (void) sigsetmask (1<<(SIGTSTP-1) | 1<<(SIGTTIN-1) | 1<<(SIGTTOU-1));
  269. #endif
  270. #endif
  271. #ifdef TIOCGPGRP
  272.     if (ioctl (0, TIOCGPGRP, (char *) &tpgrp) != 0)
  273.     {
  274.     (void) fprintf (stderr, TERM_C_NO_BATCH);
  275.     exit (1);
  276.     }
  277. #endif
  278. #ifdef SIGTSTP
  279. #ifdef TIOCPGRP
  280.     if (tpgrp != getpgrp(0)) /* not in foreground */
  281.     {
  282. #ifndef USG
  283.     (void) sigsetmask (1 << (SIGTSTP - 1) | 1 << (SIGTTIN - 1));
  284. #endif
  285.     (void) signal (SIGTTOU, SIG_DFL);
  286.     (void) kill (0, SIGTTOU);
  287.     /* job stops here waiting for SIGCONT */
  288.     goto retry;
  289.     }
  290. #endif
  291. #endif
  292.  
  293. #ifndef USG
  294.     (void) ioctl (0, TIOCGETP, (char *) &osbuf);
  295. #ifdef TIOCGLTC
  296.     (void) ioctl (0, TIOCGLTC, (char *) &oltc);
  297. #endif
  298.     termchanged = 1;
  299.  
  300.     sbuf = osbuf;
  301.     sbuf.sg_flags &= ~ECHO;
  302.     sbuf.sg_flags |= TERM_MODE;
  303.     (void) ioctl (0, TIOCSETP, (char *) &sbuf);
  304.  
  305.     uerasechar = sbuf.sg_erase;
  306.     ukillchar = sbuf.sg_kill;
  307.  
  308. #ifdef TIOCSLTC
  309.     ltc = oltc;
  310.     ltc.t_suspc = -1;
  311.     (void) ioctl (0, TIOCSLTC, (char *) <c);
  312. #endif
  313.  
  314. #endif /* USG */
  315.  
  316.     if ((oldint = signal (SIGINT, SIG_IGN)) != SIG_IGN)
  317.     (void) signal (SIGINT, done);
  318.     if ((oldterm = signal (SIGTERM, SIG_IGN)) != SIG_IGN)
  319.     (void) signal (SIGTERM, done);
  320.  
  321. #ifdef SIGTSTP
  322. #ifndef USG
  323.     (void) sigsetmask (0);
  324. #endif
  325.     if ((oldttin = signal (SIGTTIN, SIG_IGN)) != SIG_IGN)
  326.     (void) signal (SIGTTIN, onstop);
  327.     if ((oldttou = signal (SIGTTOU, SIG_IGN)) != SIG_IGN)
  328.     (void) signal (SIGTTOU, onstop);
  329.     if ((oldtstp = signal (SIGTSTP, SIG_IGN)) != SIG_IGN)
  330.     (void) signal (SIGTSTP, onstop);
  331. #endif
  332.     if (ti)
  333.     tputs (ti, 1, putch);
  334.     }
  335.  
  336. /* ARGSUSED */
  337. SIGNAL_TYPE done (signo)
  338.     int        signo;
  339.     {
  340.     if (tempfile[0] != '\0')
  341.     (void) unlink (tempfile);
  342.     if (termchanged)
  343.     {
  344.     if (te)
  345.         tputs (te, 1, putch);
  346. #ifdef USG
  347.     (void) ioctl (0, TCSETAW, (char *) &osbuf);
  348. #else
  349.     (void) ioctl (0, TIOCSETP, (char *) &osbuf);
  350. #ifdef TIOCSLTC
  351.     (void) ioctl (0, TIOCSLTC, (char *) &oltc);
  352. #endif
  353. #endif
  354.     }
  355.     exit (0);
  356.     }
  357.  
  358. #ifdef SIGTSTP
  359. static SIGNAL_TYPE onstop (signo)
  360.     int        signo;
  361.     {
  362. #ifdef USG
  363.     (void) ioctl (0, TCSETAW, (char *) &osbuf);
  364. #else
  365.     (void) ioctl (0, TIOCSETP, (char *) &osbuf);
  366. #ifdef TIOCSLTC
  367.     (void) ioctl (0, TIOCSLTC, (char *) &oltc);
  368. #endif
  369. #endif
  370.     (void) signal (signo, SIG_DFL);
  371. #ifndef USG
  372.     (void) sigsetmask (sigblock (0) & ~(1 << (signo - 1)));
  373. #endif
  374.     (void) kill (0, signo);
  375.     /* stop here until continued */
  376.     (void) signal (signo, onstop);
  377. #ifdef USG
  378.     (void) ioctl (0, TCSETAW, (char *) &sbuf);
  379. #else
  380.     (void) ioctl (0, TIOCSETP, (char *) &sbuf);
  381. #ifdef TIOCSLTC
  382.     (void) ioctl (0, TIOCSLTC, (char *) <c);
  383. #endif
  384. #endif
  385.     }
  386. #endif
  387.  
  388. void stop ()
  389.     {
  390. #ifdef SIGTSTP
  391.     onstop (SIGTSTP);
  392. #else
  393.     /* for System V */
  394.     move (li - 1, 0);
  395.     (void) fflush (stdout);
  396.     if (getenv ("SHELL"))
  397.     (void) shellescape (getenv ("SHELL"));
  398.     else
  399.     (void) shellescape ("sh");
  400. #endif
  401.     }
  402.  
  403. /* Fork and exec a process.  Returns NZ if command found, regardless of
  404. ** command's return status.  Returns zero if command was not found.
  405. ** Doesn't use a shell.
  406. */
  407. #ifndef USESH
  408. #define NEED_SHELLESCAPE
  409. #endif /* USESH */
  410. #ifndef REGEX_LOOKUP
  411. #define NEED_SHELLESCAPE
  412. #endif /* REGEX_LOOKUP */
  413. #ifdef NEED_SHELLESCAPE
  414. int shellescape    (buf)
  415.     char *    buf;
  416.     {
  417.     char *    argv[100];
  418.     char *    cp = buf;
  419.     int        i = 0;
  420.     int        termstat;
  421.  
  422.     /* parse buf to args (destroying it in the process) */
  423.     while (*cp != '\0')
  424.     {
  425.     while (*cp == ' '  ||  *cp == '\t')
  426.         ++cp;
  427.     if (*cp == '\0')
  428.         break;
  429.     argv[i++] = cp;
  430.     while (*cp != ' '  &&  *cp != '\t'  &&  *cp != '\0')
  431.         ++cp;
  432.     if (*cp != '\0')
  433.         *cp++ = '\0';
  434.     }
  435.     argv[i] = NULL;
  436.  
  437. #ifdef USG
  438.     (void) ioctl (0, TCSETAW, (char *) &osbuf);
  439. #else
  440.     (void) ioctl (0, TIOCSETP, (char *) &osbuf);
  441. #ifdef TIOCSLTC
  442.     (void) ioctl (0, TIOCSLTC, (char *) &oltc);
  443. #endif /* TIOCSLTC */
  444. #endif
  445.     (void) signal (SIGINT, oldint);
  446.     (void) signal (SIGTERM, oldterm);
  447. #ifdef SIGTSTP
  448.     (void) signal (SIGTTIN, oldttin);
  449.     (void) signal (SIGTTOU, oldttou);
  450.     (void) signal (SIGTSTP, oldtstp);
  451. #endif
  452.     if ((i = fork ()) == 0)
  453.     {
  454.     (void) execvp (argv[0], (char **) argv);
  455.     _exit (123);        /* Command not found */
  456.     }
  457.     else if (i > 0)
  458.     {
  459.     while (wait (&termstat) != i)
  460.         ;
  461.     termstat = (termstat == (123 << 8)) ? 0 : -1;
  462.     }
  463.     else
  464.     {
  465.     (void) printf (TERM_C_CANT_FORK);
  466.     termstat = -1;        /* Couldn't fork */
  467.     }
  468.  
  469.     if (oldint != SIG_IGN)
  470.     (void) signal (SIGINT, done);
  471.     if (oldterm != SIG_IGN)
  472.     (void) signal (SIGTERM, done);
  473.  
  474. #ifdef SIGTSTP
  475.     if (oldttin != SIG_IGN)
  476.     (void) signal (SIGTTIN, onstop);
  477.     if (oldttou != SIG_IGN)
  478.     (void) signal (SIGTTOU, onstop);
  479.     if (oldtstp != SIG_IGN)
  480.     (void) signal (SIGTSTP, onstop);
  481. #endif
  482.  
  483. #ifdef USG
  484.     (void) ioctl (0, TCSETAW, (char *) &sbuf);
  485. #else
  486.     (void) ioctl (0, TIOCSETP, (char *) &sbuf);
  487. #ifdef TIOCSLTC
  488.     (void) ioctl (0, TIOCSLTC, (char *) <c);
  489. #endif /* TIOCSLTC */
  490. #endif
  491.     if (termstat)
  492.     {
  493.     (void) printf (TERM_C_TYPE_SPACE);
  494.     (void) fflush (stdout);
  495. #ifdef COMMANDFORSPACE
  496.     i = GETKEYSTROKE ();
  497.     if (i != ' ' && i != '\n' && i != '\r')
  498.         (void) ungetc (i, stdin);
  499. #else
  500.     while (GETKEYSTROKE () != ' ')
  501.         ;
  502. #endif
  503.     }
  504.     return (termstat);
  505.     }
  506. #endif /* NEED_SHELLESCAPE */
  507.  
  508. #ifdef    USESH
  509. void shescape (buf)
  510.     char *    buf;
  511.     {
  512. #ifdef COMMANDFORSPACE
  513.     int        ch;
  514. #endif
  515.  
  516. #ifdef USG
  517.     (void) ioctl (0, TCSETAW, (char *) &osbuf);
  518. #else
  519.     (void) ioctl (0, TIOCSETP, (char *) &osbuf);
  520. #ifdef TIOCSLTC
  521.     (void) ioctl (0, TIOCSLTC, (char *) &oltc);
  522. #endif
  523. #endif
  524.     (void) signal (SIGINT, oldint);
  525.     (void) signal (SIGTERM, oldterm);
  526. #ifdef SIGTSTP
  527.     (void) signal (SIGTTIN, oldttin);
  528.     (void) signal (SIGTTOU, oldttou);
  529.     (void) signal (SIGTSTP, oldtstp);
  530. #endif
  531.  
  532.     (void) system (buf);
  533.  
  534.     if (oldint != SIG_IGN)
  535.     (void) signal (SIGINT, done);
  536.     if (oldterm != SIG_IGN)
  537.     (void) signal (SIGTERM, done);
  538.  
  539. #ifdef SIGTSTP
  540.     if (oldttin != SIG_IGN)
  541.     (void) signal (SIGTTIN, onstop);
  542.     if (oldttou != SIG_IGN)
  543.     (void) signal (SIGTTOU, onstop);
  544.     if (oldtstp != SIG_IGN)
  545.     (void) signal (SIGTSTP, onstop);
  546. #endif
  547.  
  548. #ifdef USG
  549.     (void) ioctl (0, TCSETAW, (char *) &sbuf);
  550. #else
  551.     (void) ioctl (0, TIOCSETP, (char *) &sbuf);
  552. #ifdef TIOCSLTC
  553.     (void) ioctl (0, TIOCSLTC, (char *) <c);
  554. #endif
  555. #endif
  556.     (void) printf (TERM_C_TYPE_SPACE);
  557.     (void) fflush (stdout);
  558. #ifdef COMMANDFORSPACE
  559.     ch = GETKEYSTROKE ();
  560.     if (ch != ' '  &&  ch != '\n'  &&  ch != '\r')
  561.     (void) ungetc (ch, stdin);
  562. #else
  563.     while (GETKEYSTROKE () != ' ')
  564.     ;
  565. #endif
  566.     }
  567. #endif
  568.